package com.bdv.md.controller;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;

import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.bdv.md.controller.xmlattribute.Parameter;
import com.bdv.md.controller.xmlattribute.TselTlkm;
import com.bdv.md.controller.xmlattribute.TlkmTsel;
import com.bdv.md.en.HTTPValues;
import com.bdv.md.en.UrlList;


@Controller
@RequestMapping("/ussd_dummy")
public class USSDControllerDummy {
	Logger logger = Logger.getLogger(this.getClass());
	
	public String getResponseStatus(String type, Integer status){
		Parameter param = new Parameter();
		param.setResponseStatus(status.toString());
		TselTlkm tsel = new TselTlkm(type, param);
		return parseTselToXML(tsel);
	}

	@RequestMapping("/token")
	public @ResponseBody String token(HttpServletRequest req){
		String xml = getXMLFromRequest(req);
		TlkmTsel tsel = parseXMLtoTlkm(xml);
		Parameter param = tsel.getParam();
		String trxId = param.getTrxId();
		String accessCode = param.getAccessCode();
		String utilityCode = param.getUtilityCode();
		String meterNumber = param.getMeterNumber();
		String meterID = param.getMeterID();
		String balanceKWH = "3000kWh";
		String suksesStatus = "1";
		String jenisToken = "6";
		String paymentMode = "1";
		
		Parameter paramResp = new Parameter(trxId, accessCode, utilityCode, meterNumber, meterID, balanceKWH, suksesStatus, jenisToken, paymentMode);
		TselTlkm respTsel = new TselTlkm(HTTPValues.TYPE_TOPUP_RESULT.getName(), paramResp);
		
		String url = UrlList.USSD_RESPONSE.getUrl();
		String xmlResp = parseTselToXML(respTsel);
		String response = httpRequestPost(url,xmlResp);
		
		System.out.println("MD RESPONSE : "+response);
		
		return getResponseStatus(HTTPValues.TYPE_SUBMIT_TOKEN_RESP.getName(),1);
	}
	

	@RequestMapping("/amr")
	public @ResponseBody String amr(HttpServletRequest req){
		String xml = getXMLFromRequest(req);
		TlkmTsel tsel = parseXMLtoTlkm(xml);
		Parameter param = tsel.getParam();
		String trxId = param.getTrxId();
		String accessCode = param.getAccessCode();
		String utilityCode = param.getUtilityCode();
		String meterNumber = param.getMeterNumber();
		String meterID = param.getMeterID();
		String balanceKWH = "3000kWh";
		String totalUsage = "12000kWh";
		String voltageRST = "220 V110 V240 v";
		String arusRST = "10 kA5 kA6 kA";
		String powerFactor = "10x";
		String dayaInstant = "100 kW";
		String tarifIndex = "5";
		String statusTamper = "Tamper";
		String totalOff = "10";
		String prediksiKreditHabis = "5d";
		String paymentModeMeterType = "2";
		String sudutIV = "32.524.635.9";
		String firmware = "fware";
		
		Parameter paramResp = new Parameter(trxId, accessCode, utilityCode, meterNumber, meterID, balanceKWH, 
				totalUsage, voltageRST, arusRST, powerFactor, dayaInstant, tarifIndex, statusTamper, totalOff, 
				prediksiKreditHabis, paymentModeMeterType, sudutIV, firmware);
		TselTlkm respTsel = new TselTlkm(HTTPValues.TYPE_METER_DATA.getName(), paramResp);
		
		String url = UrlList.USSD_RESPONSE.getUrl();
		String xmlResp = parseTselToXML(respTsel);
		String response = httpRequestPost(url,xmlResp);
		System.out.println("MD RESPONSE : "+response);
		return getResponseStatus(HTTPValues.TYPE_SUBMIT_READ_METER_RESP.getName(),1);
	}

	@RequestMapping("/limkredit")
	public @ResponseBody String limkredit(HttpServletRequest req){
		String xml = getXMLFromRequest(req);
		TlkmTsel tsel = parseXMLtoTlkm(xml);
		Parameter param = tsel.getParam();
		
		TselTlkm respTsel = new TselTlkm(HTTPValues.TYPE_CREDIT_LIMIT_RESULT.getName(), param);
		
		String url = UrlList.USSD_RESPONSE.getUrl();
		String xmlResp = parseTselToXML(respTsel);
		String response = httpRequestPost(url,xmlResp);
		System.out.println("MD RESPONSE : "+response);
		return getResponseStatus(HTTPValues.TYPE_SUBMIT_SET_CL_RESP.getName(),1);
	}
	@RequestMapping("histoken")
	public @ResponseBody String histoken(HttpServletRequest req){
		String xml = getXMLFromRequest(req);
		TlkmTsel tsel = parseXMLtoTlkm(xml);
		Parameter param = tsel.getParam();
		param.setToken1to5("00112233445566778899" +
						   "44556677889933221100" +
						   "12345678912345678900" +
						   "67890543210987612345" +
						   "13579086421357908642");
		
		TselTlkm respTsel = new TselTlkm(HTTPValues.TYPE_TOKEN_HIST_DATA.getName(), param);

		String url = UrlList.USSD_RESPONSE.getUrl();
		String xmlResp = parseTselToXML(respTsel);
		String response = httpRequestPost(url,xmlResp);
		System.out.println("MD RESPONSE : "+response);
		return getResponseStatus(HTTPValues.TYPE_SUBMIT_TOKEN_HIST_RESP.getName(),1);
	}
	@RequestMapping("bilhistory")
	public @ResponseBody String bilhistory(HttpServletRequest req){
		String xml = getXMLFromRequest(req);
		TlkmTsel tsel = parseXMLtoTlkm(xml);
		Parameter param = tsel.getParam();
		param.setNe1to5("12356789" +
						"98765321" +
						"67895321" +
						"13579086" +
						"24689752");
		param.setRp1to5("987654321" +
						"123456789" +
						"000000000" +
						"678954321" +
						"159827364");
		
		TselTlkm respTsel = new TselTlkm(HTTPValues.TYPE_BILLING_HIST_DATA.getName(), param);

		String url = UrlList.USSD_RESPONSE.getUrl();
		String xmlResp = parseTselToXML(respTsel);
		String response = httpRequestPost(url,xmlResp);
		System.out.println("MD RESPONSE : "+response);
		return getResponseStatus(HTTPValues.TYPE_SUBMIT_BILLING_HIST_RESP.getName(),1);
	}
	/**
	 * HTTP REQUEST POST METHOD
	 * this will send a request call to the url parameter with the xml as body
	 */
	private String httpRequestPost(String url, String xml){
		System.out.println("POST TO "+url+" XML : "+xml);
		PostMethod post = new PostMethod(url);   
		String response = null;
	    try {
	    	
	        StringRequestEntity requestEntity = new StringRequestEntity(xml);
	        post.setRequestEntity(requestEntity);
	        
	        post.setRequestEntity(requestEntity);
	        post.setRequestHeader("Content-type",  "text/xml; charset=UTF-8");
	        org.apache.commons.httpclient.HttpClient httpclient = new org.apache.commons.httpclient.HttpClient();
	        int result = httpclient.executeMethod(post);
	        
	        response = post.getResponseBodyAsString();
	        
	    } catch (IOException e) {
	        e.printStackTrace();
	        return e.getStackTrace().toString();
	    } finally {
	        post.releaseConnection();
	    }
	    return response;
	}
	private String getXMLFromRequest(HttpServletRequest request){
		StringBuilder stringBuilder = new StringBuilder();
		BufferedReader bufferedReader = null;
		try {
			InputStream inputStream = request.getInputStream();
			if (inputStream != null) {
				bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
				char[] charBuffer = new char[128];
				int bytesRead = -1;
				while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
					stringBuilder.append(charBuffer, 0, bytesRead);
				}
			} else {
				stringBuilder.append("");
			}
		} catch (IOException ex) {
			ex.printStackTrace();
			return ex.getStackTrace().toString();
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException ex) {
					ex.printStackTrace();
					return ex.getStackTrace().toString();
				}
			}
		}
		String body = stringBuilder.toString();

		return body;
	}
	private String parseTselToXML(TselTlkm tselXmlObj) {
		String xmlResult = null;

		StreamResult xmlStreamResult = new StreamResult(new ByteArrayOutputStream());

		try {
			JAXBContext jaxbContext = JAXBContext
					.newInstance(TselTlkm.class);
			Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            
			jaxbMarshaller.marshal(tselXmlObj, xmlStreamResult);

			xmlResult = xmlStreamResult.getOutputStream().toString();
			return xmlResult;

		} catch (JAXBException e) {
			e.printStackTrace();
			return null;
		}

	}

	private TlkmTsel parseXMLtoTlkm(String xml){
		
		try {
			JAXBContext jc = JAXBContext.newInstance(TlkmTsel.class);
	        Unmarshaller unmarshaller = jc.createUnmarshaller();
	        StreamSource xmlSource = new StreamSource(new StringReader(xml));
	        TlkmTsel tsel = (TlkmTsel)unmarshaller.unmarshal(xmlSource);
			return tsel;
		} catch (JAXBException e) {
			e.printStackTrace();
			return null;
		}
	}
}
